package com.tongji.diy.model.furniturePlacementOptimization
{
	import com.tongji.diy.model.furniturePlacementOptimization.assembleComplement.Bedding;
	import com.tongji.diy.model.furniturePlacementOptimization.assembleComplement.BeddingNearby;
	import com.tongji.diy.model.furniturePlacementOptimization.assembleComplement.FurnitureBase;
	import com.tongji.diy.model.furniturePlacementOptimization.assembleComplement.Seat;
	import com.tongji.diy.model.furniturePlacementOptimization.assembleComplement.SeatNearby;
	import com.tongji.diy.utils.PolygonMath;
	
	import flash.geom.Point;

	public class CostComputing
	{
		private var data:DataAndFunction;
		public function CostComputing(data:DataAndFunction)
		{
			this.data = data;
		}
		
		public function cost_symmetry():Number
		{
			var symmetry:Number = 0;
			if(data.symetrySign)
			{
				for(var i:int = 0; i < data.symetryList.length; ++i)
				{
					var symmetryFur:FurnitureBase =data.symetryList[i][1] ;
					var p1:Point = data._furnitureBlock.boundingBox[0].add(data._furnitureBlock.boundingBox[1]);
					p1.x /= 2;
					p1.y /= 2;
					var p2:Point = data._furnitureBlock.boundingBox[2].add(data._furnitureBlock.boundingBox[3]);
					p2.x /= 2;
					p2.y /= 2;
					var tempSymmtery:Number = 0;
					//从data.symetryList[i][0]到data.symetryList[i][1]的对称性距离
					var nearbyLocation:Point = new Point(data.symetryList[i][0].x, data.symetryList[i][0].y)
					var pedal:Point = PolygonMath.pedal(p1,p2,nearbyLocation);
					var symmetryPoint:Point = new Point(2*pedal.x - nearbyLocation.x, 2*pedal.y - nearbyLocation.y);
					var distance:Point = symmetryPoint.subtract(new Point(symmetryFur.x, symmetryFur.y));
					tempSymmtery += Math.abs((Math.sin(data.symetryList[i][0].angle) + Math.sin(symmetryFur.angle)))*OptimizationParameter.SYEMMTRY_COEFFICIENT;
					tempSymmtery += distance.length * .7;
					tempSymmtery *= data.symetryList[i][0].weight;
					symmetry += tempSymmtery;
					//从data.symetryList[i][1]到data.symetryList[i][0]的对称性距离
					symmetryFur =data.symetryList[i][0] ;
					nearbyLocation = new Point(data.symetryList[i][1].x, data.symetryList[i][1].y)
					pedal = PolygonMath.pedal(p1,p2,nearbyLocation);
					symmetryPoint= new Point(2*pedal.x - nearbyLocation.x, 2*pedal.y - nearbyLocation.y);
					distance = symmetryPoint.subtract(new Point(symmetryFur.x, symmetryFur.y));
					tempSymmtery += Math.abs((Math.sin(data.symetryList[i][1].angle) + Math.sin(symmetryFur.angle)))*OptimizationParameter.SYEMMTRY_COEFFICIENT;
					tempSymmtery += distance.length * .7;
					tempSymmtery *= data.symetryList[i][1].weight;
					symmetry += tempSymmtery;
					//symmetry *= data.symetryList[i][0].weight*.3;
				}
			}
			return symmetry//*1.1;
		}
		
		public function cost_angle(nearby:FurnitureBase):Number	
		{
			var angleCost:Number = 0;
			//nearby的方向向量
			var nearbyV:Point = new Point(-Math.sin(nearby.angle), -Math.cos(nearby.angle));
			
			if(nearby is SeatNearby)
			{
				data._furnitureBlock.furVector.forEach(seatNearbyForEach);
				return angleCost*nearby.weight*60*.5;
			}
			else if(nearby is BeddingNearby)
			{
				data._furnitureBlock.furVector.forEach(beddingNearbyForEach);
				return angleCost*nearby.weight*60*.5;
			}
			return 0;
			
			function seatNearbyForEach(item:Object, index:int, v:*):void
			{
				if(item is Seat)
				{	
					var temp:Point = new Point((item as Seat).x - nearby.x, (item as Seat).y - nearby.y);
					var len:Number = temp.length;
					temp.x = temp.x / len;
					temp.y = temp.y / len;
					var itemV:Point = new Point(-Math.sin((item as Seat).angle), -Math.cos((item as Seat).angle));
					//满足美观性要求，即使得nearby家具能够尽量垂直于或者平行于seat
					angleCost += Math.abs(Math.sin(Math.acos((itemV.x * nearbyV.x + itemV.y * nearbyV.y))*2)) *(item as Seat).weight*1.5
						//满足使得nearby家具能够与seat家具面对面摆放,保证朝向是面向seat的
						+ (itemV.x*nearbyV.x + itemV.y*nearbyV.y)*(item as Seat).weight*1.5
						//保证是放置在seat的正前方
						+ (temp.x * itemV.x + temp.y * itemV.y)*(item as Seat).weight*1.5;
					angleCost *= (item as Seat).weight;
				}
			}
			
			function beddingNearbyForEach(item:Object, index:int, v:*):void
			{
				if(item is Bedding)
				{
					var temp:Point = new Point((item as Bedding).x - nearby.x ,(item as Bedding).y - nearby.y);
					var len:Number = temp.length;
					temp.x = temp.x / len;
					temp.y = temp.y / len;
					var itemV:Point = new Point(-Math.sin((item as Bedding).angle),- Math.cos((item as Bedding).angle));
					angleCost += Math.abs(Math.sin(Math.acos((itemV.x * nearbyV.x + itemV.y * nearbyV.y))*2)) *(item as Bedding).weight*1.5
						+ (itemV.x*nearbyV.x + itemV.y*nearbyV.y)
						+ temp.x * itemV.x + temp.y * itemV.y;
					angleCost *= (item as Bedding).weight;
				}
			}
		}
		
		public function cost_distance(nearby:FurnitureBase):Number
		{
			var distance:Number = 0;
			if(nearby is SeatNearby)
			{
				data._furnitureBlock.furVector.forEach(seatNearbyForEach);
				return distance*nearby.weight*.51;
			}
			else if(nearby is BeddingNearby)
			{
				data._furnitureBlock.furVector.forEach(beddingNearbyForEach);
				return distance*nearby.weight*.51;
			}
			return 0;
			
			//distance += Math.sqrt((data._furnitureBlock.x - nearby.x)*(data._furnitureBlock.x - nearby.x));
			//	+ (data._furnitureBlock.y - nearby.y)*(data._furnitureBlock.y - nearby.y)) *.2;
			
			
			
			function seatNearbyForEach(item:FurnitureBase, index:int, v:*):void
			{
				if(item is Seat)
				{
					distance += (item as Seat).weight * Math.sqrt((nearby.x - (item as Seat).accX)*(nearby.x - (item as Seat).accX) + (nearby.y - (item as Seat).accY)*(nearby.y - (item as Seat).accY)); 
					distance += PolygonMath.pointToRectangleDistance(new Point(nearby.accX,nearby.accY), item.accessibleBox)*.5;
				}
			}
			
			function beddingNearbyForEach(item:FurnitureBase, index:int, v:*):void
			{
				if(item is Bedding)
				{
					distance += (item as Bedding).weight * Math.sqrt((nearby.x - (item as Bedding).accX)*(nearby.x - (item as Bedding).accX) + (nearby.y - (item as Bedding).accY)*(nearby.y - (item as Bedding).accY));
					distance += PolygonMath.pointToRectangleDistance(new Point(nearby.accX,nearby.accY), item.accessibleBox)*.5;
				}
			}
		}
	}
}